package com.rising.face.ali.bishi.threadprint5;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static java.lang.Thread.State.WAITING;

/**
 * @Author: rising
 * @Description:
 * // 设计一个多线程打印程序，第i个线程只打印i-1数字，比如第1个线程打印数字0，第2个线程只打印数字1，依次类推。
 * // 任意给定一个数字序列，比如5743958490143058，能够使用该程序打印出来。
 *
 * thread1 = 0
 * thread2 = 1
 * ....
 * thread6 = 5
 * thread8 = 7
 * thread9 = 8
 * thread0 = 9
 * @Date: create in 2021/3/26 21:44
 */

public class ThreadPrint5 {
    private int currentThread = 0;
    private int index = 0;
    private int[] xulie = null;

    private Lock lock = new ReentrantLock();

    private Condition[] conditions = null;

    private Thread[] threads = null;

    public Thread[] getThreads() {
        return threads;
    }

    //传入第一个唤醒线程
    public ThreadPrint5(String currentThreads) {
        char[] chars = currentThreads.toCharArray();
        xulie = new int[chars.length];
        for (int i = 0; i < chars.length; i++) {
            xulie[i] = Integer.valueOf(String.valueOf(chars[i]));
        }

        //第一个打印的线程
        currentThread = xulie[0];

        conditions = new Condition[10];
        threads = new Thread[10];
        System.out.println("开始初始化。。。。。");
        for (int i = 0; i < 10; i ++) {
            conditions[i] = lock.newCondition();
            System.out.println("conditions[" + i + "]" + conditions[i]);
            threads[i] = new Thread(new MyRunnable(this), i + "");
        }
        System.out.println("初始化完毕。。。。。");

        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }

    }

    public static class MyRunnable implements Runnable {

        private ThreadPrint5 thread;

        public MyRunnable(ThreadPrint5 thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            thread.print();
        }
    }

    public void print() {
        int threadName = Integer.valueOf(Thread.currentThread().getName());
        int flag = threadName == 0 ? 9 : (threadName - 1) % 9;
        try {
            lock.lock();
            while (true) {
                //等待唤醒
                while (currentThread != flag) {
                    //System.out.println("当前等待线程");
                    conditions[flag].await();
                }

                System.out.println("当前线程：Thread" + Thread.currentThread().getName()
                        + " -打印- " + xulie[index]
                        + " 唤醒下个线程：Thread" + (currentThread + 1) % 10
                        + " 索引：" + index);

                //找到下一个需要唤醒的线程
                index++;
                if (index >= xulie.length) {
                    break;
                }
                currentThread = xulie[index];
                //唤醒线程
                conditions[currentThread].signal();
            }
        } catch (Exception e) {
            System.out.println("当前等待线程：" + threadName + " 打印条件：" + flag + " 当前执行线程：" + currentThread + " conditions:" + conditions[flag]);
            for (int i = 0; i < conditions.length; i++) {
                System.out.println(conditions[i]);
            }
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        String currentThreads = "5743958490143058";
        //String currentThreads = "57";
        ThreadPrint5 threadPrint = new ThreadPrint5(currentThreads);

        Thread[] threads = threadPrint.getThreads();

    }
}
